import { Body, Controller, Get, Headers, Logger, Param, Post, Query, UseGuards } from '@nestjs/common'
import { ApiOperation, ApiTags } from '@nestjs/swagger'

import { ApiResult } from '~/common/decorators/api-result.decorator'
import { Bypass } from '~/common/decorators/bypass.decorator'
import { IotEventDto } from '~/modules/health/iot/iot.dto'

import { Public } from '../../auth/decorators/public.decorator'
import { LocalGuard } from '../../auth/guards/local.guard'
import { DeviceAttrDto, DeviceAuthDto, DeviceConfigDto, DeviceSignDto } from '../device/device.dto'
import { DeviceToken } from '../device/device.model'
import { UserDataDto } from '../user/userData.dto'
import { IotService } from './iot.service'

@ApiTags('Auth - 设备认证模块')
@UseGuards(LocalGuard)
@Public()
@Controller('v1')
export class IotController {
  private logger = new Logger(IotController.name)

  constructor(
    private iotService: IotService,
  ) { }

  @Post('auth')
  @ApiOperation({ summary: '设备认证' })
  @ApiResult({ type: DeviceToken })
  async auth(@Query() query: DeviceSignDto, @Body() authDto: DeviceAuthDto): Promise<DeviceToken> {
    this.logger.debug(`query: ${JSON.stringify(query)}, body: ${JSON.stringify(authDto)}`)
    return this.iotService.auth(authDto, query)
  }

  @Post(':uid/attribute')
  @ApiOperation({ summary: '设备属性上报' })
  async saveAttribute(@Headers('Authorization') token: string, @Param('uid') uid: string, @Body() data: DeviceAttrDto): Promise<void> {
    this.logger.debug(`uid: ${uid}, body: ${JSON.stringify(data)}`)
    await this.iotService.validateToken(token, uid)
    await this.iotService.saveAttr(uid, data)
  }

  @Get(':uid/attribute')
  @ApiOperation({ summary: '设备属性查询' })
  async queryAttribute(@Headers('Authorization') token: string, @Param('uid') uid: string): Promise<DeviceConfigDto[]> {
    // this.logger.debug(`uid: ${uid}`)
    await this.iotService.validateToken(token, uid)
    return this.iotService.getAttr(uid)
  }

  @Post(':uid/data')
  @ApiOperation({ summary: '设备数据上报' })
  async saveData(@Headers('Authorization') token: string, @Param('uid') uid: string, @Body() data: UserDataDto[]): Promise<void> {
    this.logger.debug(`token: ${token}`)
    this.logger.debug(`uid: ${uid}, body: ${JSON.stringify(data)}`)
    const device = await this.iotService.validateToken(token, uid)
    await this.iotService.saveData(device, data)
  }

  @Post(':uid/event')
  @ApiOperation({ summary: '设备事件上报' })
  async onEvent(@Headers('Authorization') token: string, @Param('uid') uid: string, @Body() event: IotEventDto): Promise<void> {
    this.logger.debug(`uid: ${uid}, body: ${JSON.stringify(event)}`)
    const device = await this.iotService.validateToken(token, uid)
    await this.iotService.handleEvent(device, event)
  }

  @Get(':uid/event')
  @ApiOperation({ summary: '设备事件查询' })
  async queryEvent(@Headers('Authorization') token: string, @Param('uid') uid: string, @Query('timeout') timeout: number): Promise<void> {
    if (!timeout) {
      timeout = 3000
    }
    this.logger.debug(`uid: ${uid}, timeout: ${timeout}`)
    await this.iotService.validateToken(token, uid)
    while (timeout) {
      await new Promise(resolve => setTimeout(resolve, 100))
      timeout -= 100
    }
    // this.iotService.saveData(uid, data)
  }

  @Post('test')
  @ApiOperation({ summary: '测试接口' })
  @Bypass()
  async test(@Query() query: any, @Body() body: any): Promise<any> {
    query && this.logger.debug(`query: ${JSON.stringify(query)}`)
    body && this.logger.debug(`body: ${JSON.stringify(body)}`)
    return {
      IsSuccess: true,
      Message: '上传成功',
      Exception: '',
      ErrorCode: -1,
      Sql: '',
    }
  }
}
